/*******************************************************************************
 * Copyright (c) 2008 Nels E. Beckman.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Nels E. Beckman - initial API and implementation
 *******************************************************************************/
package edu.cmu.cs.nbeckman.wptransltor.util;

/**
 * Option type. So glad I create one of these every time I work on a project!
 * 
 * @author Nels E. Beckman
 */
public abstract class Option<T> {

	@SuppressWarnings("unchecked")
	private static final None NONE_INSTANCE = new None();
	
	@SuppressWarnings("unchecked")
	public static <S> None<S> none() {
		return NONE_INSTANCE;
	}
	
	public static <S> Some<S> some(S item) {
		return new Some<S>(item);
	}
	
	/**
	 * Is there an item here?
	 */
	public abstract boolean isSome();
	/**
	 * Is there no item here?
	 */
	public abstract boolean isNone();
	/**
	 * Unwraps the option. This will only work if
	 * {@code isSome()} returns {@code true}. Otherwise
	 * will throw an exception.
	 */
	public abstract T unwrap();
	
	static class UnwrapException extends RuntimeException {
		/** Never Change. */
		private static final long serialVersionUID = 1L;
	}
	
	static class Some<S> extends Option<S> {

		private final S item;
		
		public Some(S item) {
			this.item = item;
		}
		
		@Override public boolean isNone() { return false; }
		@Override public boolean isSome() { return true; }
		@Override public S unwrap() { return item; }
	}
	
	static class None<S> extends Option<S> {
		@Override public boolean isNone() { return true; }
		@Override public boolean isSome() { return false; }
		@Override public S unwrap() { throw new UnwrapException(); }
	}
}
